package com.example.score.service;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.example.score.dto.StudentInfoListDto;
import com.example.score.dto.StudentInfoListVo;
import com.example.score.dto.StudentInfoVo;
import com.example.score.entity.ExamBase;
import com.example.score.entity.ExamDetail;
import com.example.score.entity.GradeInfo;
import com.example.score.entity.StudentSubmit;
import com.example.score.mapper.ExamBaseMapper;
import com.example.score.mapper.ExamDetailMapper;
import com.example.score.mapper.GradeInfoMapper;
import com.example.score.mapper.StudentSubmitMapper;
import com.example.score.service.oms.bean.GetStudentByStudentNumberOutPut;
import com.example.score.service.oms.OmsService;
import com.example.score.utils.constants.DateConstants;
import lombok.RequiredArgsConstructor;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.text.DecimalFormat;
import java.time.LocalDate;
import java.util.*;
import java.util.stream.Collectors;

@Service
@RequiredArgsConstructor
public class StudentService {

    private final StudentSubmitMapper studentSubmitMapper;
    private final ExamDetailMapper examDetailMapper;
    private final GradeInfoMapper gradeInfoMapper;
    private final ExamBaseMapper examBaseMapper;
    private final OmsService omsService;
    private final TeacherStarStudentService teacherStarStudentService;

    /**
     * 学生登录
     *
     * @param studentNum  准考证号
     * @param studentName 姓名
     * @return 学生信息
     */
    public Map<String, Object> login(String studentNum, String studentName) {
        Map<String, Object> student = studentSubmitMapper.findStudent(studentNum, studentName);
        if (student == null) {
            throw new RuntimeException("学生信息不存在或准考证号与姓名不匹配");
        }
        //调用oms获取当前学生的绑定情况 0未绑定 1已绑定examBase.getSchoolNumber() + studentDTO.getStudentNum()
        GetStudentByStudentNumberOutPut getStudentByStudentNumberOutPut = omsService.getStudentByStudentNumber(studentNum);
        student.put("student", getStudentByStudentNumberOutPut);
        return student;
    }

    /**
     * 获取学生作业列表
     *
     * @param studentNum 准考证号
     * @param subjectId
     * @param gradeId
     * @param startTime
     * @param endTime
     * @param type
     * @return 作业列表
     */
    public List<Map<String, Object>> getHomeworkList(String studentNum, Long subjectId, Long gradeId, LocalDate startTime, LocalDate endTime, Integer type) {
        // 2. 获取时间范围
        if (!Objects.isNull(type)) {
            endTime = LocalDate.now();
            if (type == DateConstants.WEEK) {
                // 周度：当前日期7天
                startTime = LocalDate.now().minusDays(6);
            } else if (type == DateConstants.MONTH) {
                // 月度：当前日期30天
                startTime = LocalDate.now().minusDays(29);
            }
        }
        List<Map<String, Object>> homeworkList = new ArrayList<>();
        List<StudentSubmit> studentSubmitList = studentSubmitMapper.selectExamDetailIdByStudentNum(studentNum);
        List<Long> allExamDetailIds = studentSubmitList.stream().map(StudentSubmit::getExamDetailId).collect(Collectors.toList());
        if (ObjectUtils.isNotEmpty(gradeId)) {
            List<GradeInfo> gradeInfoList = gradeInfoMapper.selectByGradeId(gradeId);
            List<Long> finalAllExamDetailIds = allExamDetailIds;
            allExamDetailIds = gradeInfoList.stream().filter(g -> finalAllExamDetailIds.contains(g.getExamDetailId())).collect(Collectors.toList())
                    .stream().map(GradeInfo::getExamDetailId).collect(Collectors.toList());
        }
        List<ExamDetail> examDetailList = examDetailMapper.selectListByExamDetailIds(allExamDetailIds);
        if (ObjectUtils.isNotEmpty(subjectId)) {
            examDetailList = examDetailList.stream().filter(d -> d.getSubjectOnlyid().equals(subjectId)).collect(Collectors.toList());
        }
        List<Long> examIds = examDetailList.stream().map(ExamDetail::getExamId).collect(Collectors.toList());
        List<ExamBase> examBaseList = examBaseMapper.selectByExamIds(examIds);
        for (ExamBase examBase : examBaseList) {
            // 检查考试时间是否在指定范围内
            if (ObjectUtils.isNotEmpty(type)) {
                LocalDate examDate = examBase.getStartTime().toLocalDate();
                if (examDate.isBefore(startTime) || examDate.isAfter(endTime)) {
                    continue; // 如果不在时间范围内，跳过当前循环
                }
            }
            ExamDetail examDetail = examDetailList.stream().filter(ed -> ed.getExamId().equals(examBase.getExamId())).findFirst().get();
            StudentSubmit studentSubmit = studentSubmitList.stream().filter(s -> s.getExamDetailId().equals(examDetail.getId())).findFirst().get();
            Map<String, Object> homework = new HashMap<>();
            homework.put("examDetailId", examDetail.getId());
            homework.put("examId", examBase.getExamId());
            homework.put("score", studentSubmit.getScore());
            homework.put("status", studentSubmit.getSubmitStatus());
            homework.put("examName", examBase.getExamName());
            homework.put("submitTime", examBase.getStartTime());
            homework.put("subjectId", examDetail.getSubjectOnlyid());
            homeworkList.add(homework);
        }

        if (homeworkList.isEmpty()) {
            throw new RuntimeException("未找到该学生的作业信息");
        }
        return homeworkList;
    }

    public List<Map<String, Object>> getSutdentSubjectList(Long studentNum) {
        List<StudentSubmit> studentSubmitList = studentSubmitMapper.selectExamDetailIdByStudentNum(studentNum.toString());
        List<Long> allExamDetailIds = studentSubmitList.stream().map(StudentSubmit::getExamDetailId).collect(Collectors.toList());
        List<GradeInfo> gradeInfoList = gradeInfoMapper.selectByExamDetailIds(allExamDetailIds);
        List<ExamDetail> examDetailList = examDetailMapper.selectListByExamDetailIds(allExamDetailIds);
        // 按照 gradeId 分组，并对每个分组内的科目去重
        Map<Long, List<Map<String, Object>>> groupedResult = examDetailList.stream()
                .map(examDetail -> {
                    GradeInfo gradeInfo = gradeInfoList.stream()
                            .filter(g -> g.getExamDetailId().equals(examDetail.getId()))
                            .findFirst()
                            .orElse(null);
                    if (gradeInfo == null) return null;

                    Map<String, Object> subjectMap = new HashMap<>();
                    subjectMap.put("gradeId", gradeInfo.getGradeId());
                    subjectMap.put("gradeName", gradeInfo.getGradeName());
                    subjectMap.put("subjectId", examDetail.getSubjectOnlyid());
                    subjectMap.put("subjectName", examDetail.getSubjectName());
                    return subjectMap;
                })
                .filter(Objects::nonNull)
                .collect(Collectors.groupingBy(
                        map -> (Long) map.get("gradeId"),
                        Collectors.collectingAndThen(
                                Collectors.toMap(
                                        map -> (Long) map.get("subjectId"),
                                        map -> map,
                                        (existing, replacement) -> existing
                                ),
                                map -> new ArrayList<>(map.values())
                        )
                ));

        // 将分组结果转换为最终列表
        List<Map<String, Object>> result = new ArrayList<>();
        groupedResult.forEach((gradeId, subjects) -> {
            Map<String, Object> gradeMap = new HashMap<>();
            gradeMap.put("gradeId", gradeId);
            gradeMap.put("gradeName", subjects.get(0).get("gradeName")); // 使用第一个科目的年级名称
            gradeMap.put("subjectList", subjects);
            result.add(gradeMap);
        });
        return result;
    }

    public StudentInfoVo getStudentInfo(String studentId, Long classId, Long examId) {
        ExamBase examBase = examBaseMapper.selectByExamId(examId);
        if (Objects.isNull(examBase)) {
            throw new RuntimeException("考试（作业）信息不存在。");
        }

        ExamDetail examDetail = examDetailMapper.selectByExamId(examId);
        if (Objects.isNull(examDetail)) {
            throw new RuntimeException("考试（作业）信息不存在。");
        }

        StudentSubmit studentSubmit = studentSubmitMapper.selectByStudentIdAndSubmit(studentId, classId, examDetail.getId());
        if (Objects.isNull(studentSubmit)) {
            throw new RuntimeException("学生信息不存在。");
        }

        double score = studentSubmit.getScore();
        Integer fullScore = examDetail.getFullScore();

        List<StudentSubmit> studentSubmits = studentSubmitMapper.selectByStudentSort(classId, examDetail.getId());
        //拿到排名
        List<Long> studentSubmitIds = studentSubmits.stream()
                .sorted(Comparator.comparing(StudentSubmit::getScore).reversed())
                .map(StudentSubmit::getId).collect(Collectors.toList());
        //学生排名
        int sort = studentSubmitIds.indexOf(studentSubmit.getId()) + 1;
        //拿到平均分
        double avgScore = studentSubmits.stream().mapToDouble(StudentSubmit::getScore).average().orElse(0.0);

        StudentInfoVo studentInfoVo = new StudentInfoVo();
        studentInfoVo.setStudentSubmitId(studentSubmit.getId());
        studentInfoVo.setStudentId(studentSubmit.getStudentId());
        studentInfoVo.setStudentName(studentSubmit.getStudentName());
        studentInfoVo.setExamName(examBase.getExamName());
        studentInfoVo.setClassSort(sort);
        studentInfoVo.setScoreMark(score + "/" + fullScore);
        DecimalFormat df1 = new DecimalFormat("0.00");
        studentInfoVo.setAvgScore(Double.valueOf(df1.format(Math.abs(avgScore - score))));
        studentInfoVo.setScoreRatio(score / fullScore * 100);
        studentInfoVo.setSubTime(studentSubmit.getUpdatedTime());
        studentInfoVo.setPaperImages(studentSubmit.getPaperImages());
        return studentInfoVo;
    }

    public List<StudentInfoListVo> getStudentInfoList(StudentInfoListDto studentInfoListDto) {
        ExamDetail examDetail = examDetailMapper.selectByExamId(studentInfoListDto.getExamId());
        if (Objects.isNull(examDetail)) {
            throw new RuntimeException("考试（作业）信息不存在！");
        }
        LambdaQueryWrapper<StudentSubmit> wrapper = new LambdaQueryWrapper<StudentSubmit>()
                .eq(StudentSubmit::getExamDetailId, examDetail.getId())
                .eq(StudentSubmit::getClassId, studentInfoListDto.getClassId())
                .eq(StudentSubmit::getSubmitStatus, 1)
                .like(StringUtils.isNotEmpty(studentInfoListDto.getStudentName()), StudentSubmit::getStudentName, studentInfoListDto.getStudentName());
        if (!CollectionUtils.isEmpty(studentInfoListDto.getStudentIds())) {
            wrapper.in(StudentSubmit::getStudentId, studentInfoListDto.getStudentIds());
        }
        List<StudentSubmit> studentSubmits = studentSubmitMapper.selectList(wrapper);

        List<Long> studentIds = teacherStarStudentService.starList(studentInfoListDto.getTeacherId());

        List<StudentInfoListVo> studentInfoListVos = new ArrayList<>();
        for (StudentSubmit studentSubmit : studentSubmits) {
            StudentInfoListVo studentInfoListVo = new StudentInfoListVo();
            BeanUtils.copyProperties(studentSubmit, studentInfoListVo);
            if(studentIds.contains(studentSubmit.getStudentId())) {
                studentInfoListVo.setStarStatus(0);
            }
            studentInfoListVos.add(studentInfoListVo);
        }
        if(studentInfoListDto.getStarStatus() == 0){
            studentInfoListVos = studentInfoListVos.stream().filter(e -> studentIds.contains(e.getStudentId())).collect(Collectors.toList());
        }
        return studentInfoListVos;
    }
}
